<?php


namespace App\Http\Util;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\DB;
use App\Model\Menus;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

class Tool
{
    /**
     * 获取redis登录态信息
     * @param $token
     * @return mixed
     */
    public static function getRedisInfo($token)
    {
        $token = $token ?? null;
        if ($token == null) {
            return false;
        }
        $info = Redis::get('login_status:' . $token);
        if (is_null($info)) {
            return false;
        }
        return json_decode($info, true);
    }

    /**
     * 判断redis登录态是否存在
     * @return bool
     */
    public static function checkRedisLoginStatus()
    {
        $token = request()->header('X-Token');
        $info = Redis::get('login_status:' . $token);
        if (is_null($info)) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 获取管理员的角色id
     * @param $token
     * @return mixed
     */
    public static function getAdminRoleId($token)
    {
        $token = $token ?? null;
        if ($token == null) {
            return false;
        }
        $info = Redis::get('login_status:' . $token);
        if (is_null($info)) {
            return false;
        }
        $arrInfo = json_decode($info, true);
        return $arrInfo['type'];
    }

    /**
     * 获取管理员的部门
     * @param $token
     * @return mixed
     */
    public static function getAdminDepartment($token)
    {
        $token = $token ?? null;
        if ($token == null) {
            return false;
        }
        $info = Redis::get('login_status:' . $token);
        if (is_null($info)) {
            return false;
        }
        $arrInfo = json_decode($info, true);
        return $arrInfo['department'];
    }

    /**
     * 是否超级管理员
     * @param $token
     * @return bool
     */
    public static function isSuperLeader($token)
    {
        $info = self::getRedisInfo($token);
        if (!$info) {
            return false;
        }

        switch ($info['type']) {
            case 1:
                return true;
            case 2:
            case 3:
            case 4:
                return false;
        }
    }

    /**
     * 是否总管理员
     * @param $token
     * @return bool
     */
    public static function isLeader($token)
    {
        $info = self::getRedisInfo($token);
        if (!$info) {
            return false;
        }
        switch ($info['type']) {
            case 2:
            case 3:
            case 4:
                return true;
            case 1:
                return false;
        }
    }

    /**
     * 获取品牌管理信息
     * @return mixed
     */
    public static function getBrandManager()
    {
        return DB::table('brand_manager')->select('id', 'brand')->get()->toArray();
    }

    /**
     * 删除登录态
     * @param $token
     * @return bool
     */
    public static function delCreateStatus($token)
    {
        $del = 'login_status:' . $token;
        $res = Redis::del($del);
        if ($res) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 检测电子邮箱在管理员是否唯一
     * @param $email
     * @return bool
     */
    public static function checkMailUnique($email)
    {
        $res = DB::table('admins')->where('email', $email)->count();
        if ($res) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 返回字符串内的数字部分
     * @param string $str
     * @return string
     */
    public static function findNum($str = '')
    {
        $str = trim($str);
        if (empty($str)) {
            return '';
        }
        $temp = array('1', '2', '3', '4', '5', '6', '7', '8', '9', '0');
        $result = '';
        for ($i = 0; $i < strlen($str); $i++) {
            if (in_array($str[$i], $temp)) {
                $result .= $str[$i];
            }
        }
        return $result;
    }

    /**
     * 格式化数字
     * 01-99显示
     * @param $num
     * @return string
     */
    public static function numFormat($num)
    {
        if (($num >= 1) && ($num <= 9)) {
            return '0' . $num;
        } else {
            return $num;
        }
    }

    /**
     * 添加水印
     * @param $imgPath /原图片路径
     * @param $waterMarkPath /水印路径
     * @param $isCreate /是否创建新图片,默认否
     * @param $newImgPath /新图片路径
     * @return bool
     */
    protected function addWaterMark($imgPath, $waterMarkPath, $isCreate = false, $newImgPath = '')
    {
        if ($isCreate) {
            $img = Image::make($imgPath)->insert($waterMarkPath, 'top-left', 10, 10);
            if ($img->save($newImgPath)) {
                return true;
            } else {
                return false;
            }
        } else {
            $img = Image::make($imgPath)->insert($waterMarkPath, 'top-left', 10, 10);
            if ($img->save($imgPath)) {
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * 比例计算图片宽高
     * @param $width
     * @param $height
     * @param $maxWidth
     * @param $maxHeight
     * @return array
     */
    public static function calculateDimensions($width, $height, $maxWidth, $maxHeight)
    {
        if ($width != $height) {
            if ($width > $height) {
                $tWidth = $maxWidth;
                $tHeight = (($tWidth * $height) / $width);
                //fix height
                if ($tHeight > $maxHeight) {
                    $tHeight = $maxHeight;
                    $tWidth = (($width * $tHeight) / $height);
                }
            } else {
                $tHeight = $maxHeight;
                $tWidth = (($width * $tHeight) / $height);
                //fix width
                if ($tWidth > $maxWidth) {
                    $tWidth = $maxWidth;
                    $tHeight = (($tWidth * $height) / $width);
                }
            }
        } else {
            $tWidth = $tHeight = min($maxHeight, $maxWidth);
        }
        return array('height' => (int)$tHeight, 'width' => (int)$tWidth);
    }

    /**
     * 获取管理员id
     * @param $token
     * @return mixed
     */
    public static function getAdminId($token)
    {
        $info = self::getRedisInfo($token);
        if (!$info) {
            return false;
        }
        return $info['id'];
    }

    /**
     * 获取部门列表
     * @return object $result
     */
    public static function getDepartment()
    {
        $result = DB::table('department')->get();
        return $result;
    }

    /**
     * 获取管理员pid
     * @param $token
     * @return mixed
     */
    public static function getAdminPid($token)
    {
        $info = self::getRedisInfo($token);
        if (!$info) {
            return false;
        }
        return $info['pid'];
    }

    /**
     * 根据部门返回部门id
     * @param string $department
     * @return mixed
     */
    public static function getDepartmentId(string $department)
    {
        return DB::table('department')->where('department', $department)->value('id');
    }

    /**
     * 根据品牌返回品牌id
     * @param string $brand
     * @return mixed
     */
    public static function getBrandId(string $brand)
    {
        return DB::table('brand_manager')->where('brand', $brand)->value('id');
    }

    /**
     * 返回随机字符串
     * @param $length
     * @return string
     */
    public static function getRandom($length)
    {
        $token = "";
        $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $codeAlphabet .= "0123456789";

        for ($i = 0; $i < $length; $i++) {
            $token .= $codeAlphabet[mt_rand(0, strlen($codeAlphabet) - 1)];
        }
        return $token;
    }

    /**
     * 返回登录态token
     * @return array|string|null
     */
    public static function getToken()
    {
        return request()->cookie('Admin-Token');
    }

    /**递归获取所有子菜单
     * @param $data
     * @return mixed
     */
    public static function getChild(&$data,$type='admin',$arr=[]){
        foreach($data as $k => $v){
            if($type == 'admin'){
                $data[$k]['children']= Menus::where('pid',$v['id'])
                    ->where('is_del', Err::DEL_SHOW)
                    ->where('status',Err::DEL_SHOW)
                    ->orderBy('sort','desc')
                    ->get(['id','name','pid','url','icon','component','status','label','sort'])
                    ->toArray();
            }else{
                $data[$k]['children']= Menus::where('pid',$v['id'])
                    ->where('is_del', Err::DEL_SHOW)
                    ->where('status',Err::DEL_SHOW)
                    ->whereIn('id',$arr)
                    ->orderBy('sort','desc')
                    ->get(['id','name','pid','url','icon','component','status','label','sort'])
                    ->toArray();
            }

            if(count($data[$k]['children'])>0){
                self::getChild($data[$k]['children']);
            }
        }
        return $data;
    }

    /**递归获取所有菜单带权限
     * @param $data
     * @return mixed
     */
    public static function rolesChild(&$data){
        foreach($data as $k => $v){
            $data[$k]['children']= Menus::where('pid',$v['id'])
                ->where('is_del',1)
                ->orderBy('sort','desc')
                ->get(['id','name','pid','url','icon','component','status','label','sort'])
                ->toArray();
            if(count($data[$k]['children'])>0){
                self::getChild($data[$k]['children']);
            }else{
                $data[$k]['children'] = ['add','edit','del','check'];
            }
        }
        return $data;
    }

//增加浏览量
    public static function addView($key){
        $bool= Redis::exists($key);
        if($bool){
            $res=Redis::incr($key);
        }
        else{
            //   $res=Redis::set($key,1,'EX',3600*24);
            $res=Redis::set($key,1);
        }
        return $res;
    }


    public static function log($name,$title,$content,$level=Logger::INFO,$file='lumen')
    {
        $log = new Logger($name);
        $log->pushHandler(new StreamHandler(storage_path
        ('logs/' . $name . '.' . $file . '.log'), 0));
        if ($level === Logger::INFO) {
            $log->addInfo($title . '：' . $content);
        } elseif ($level === Logger::ERROR) {
            $log->addError($title . '：' . $content);
        }
    }

    /**
     * 信息日志
     * @param $title
     * @param $content
     * @param string $file
     */
   public static function logInfo($title, $content, $file = 'lumen')
    {
        self::log('admin', $title, $content, Logger::INFO, $file);
    }

    /**
     * 错误日志
     * @param $title
     * @param $content
     * @param string $file
     */
    public static function logError($title, $content, $file = 'lumen')
    {
        self::log('admin', $title, $content, Logger::ERROR, $file);
    }

    /**
     * @param $data
     */
    public static function swooleCurl($data)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, "https://imm.cn-shanghai.aliyuncs.com");
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HEADER, 1);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_exec($curl);
        curl_close($curl);
    }

    /**
     *获取两个字符串之间的内容
     */
    public static function get_between($input,$start,$end){
        $str =  substr($input,strlen($start)+strpos($input,$start),(strlen($input)-strpos($input,$end)) *(-1));
        return $str;
    }

    public static function getThreeMonthsAgoMonth($num) {
        $date = new \DateTime();
        $date->modify('-'.$num.' months');
        return $date->format('Y-m');
    }


    public static function getAllDaysOfMonth($month) {
        // 创建该月的第一天
        $firstDay = new \DateTime($month . '-01');
        // 获取该月的天数
        $daysInMonth = (int)$firstDay->format('t');
        // 生成该月所有日期
        $allDays = [];
        for ($day = 1; $day <= $daysInMonth; $day++) {
            $date = new \DateTime($month . '-' . str_pad($day, 2, '0', STR_PAD_LEFT));
            $allDays[] = $date->format('Y-m-d');
        }
        return $allDays;
    }



    public static function decrCacheDu($deviceId, $du, $num) {
        // 获取月份和日期列表等
        $month = self::getThreeMonthsAgoMonth($num);

        $dates = self::getAllDaysOfMonth($month);
        $dayCount = count($dates);
        $monthKey = $deviceId . '-' . str_replace('-', '', $month);
        $dailyKeyPrefix = 'zhufang_database_'.$deviceId . '-';
        $totalDu = (int)($du * 1000); // 转为毫秒并确保为整数

        // 计算每日计划扣除量
        $dailyDu = (int)($totalDu / $dayCount);
        $adjustment = $totalDu - ($dailyDu * $dayCount); // 最后一天调整

        // 定义Lua脚本 - 关键修改
        $luaScript = <<<LUA
local key = KEYS[1]
local duToDeduct = tonumber(ARGV[1])
local balance = tonumber(redis.call('GET', key) or 0)
local actualDeducted = 0

-- 添加新逻辑：如果当前值小于等于要扣减的值，则不扣减
if balance <= duToDeduct then
    return 0
end

-- 正常扣减逻辑
actualDeducted = duToDeduct
redis.call('DECRBY', key, duToDeduct)

return actualDeducted
LUA;

        // 使用管道闭包
        try {
            $results = Redis::pipeline(function ($pipe) use ($dates, $dailyKeyPrefix, $luaScript, $dailyDu, $adjustment, $dayCount) {
                foreach ($dates as $index => $date) {
                    $dateStr = str_replace('-', '', $date);
                    $dailyKey = $dailyKeyPrefix . $dateStr;

                    // 计算该日计划扣除量（最后一天加上调整值）
                    $duToDeduct = $dailyDu;
                    if ($index == $dayCount - 1) {
                        $duToDeduct += $adjustment;
                    }

                    Log::info("每日扣除计划", [
                        'date' => $date,
                        'dailyKey' => $dailyKey,
                        'duToDeduct' => $duToDeduct
                    ]);

                    $pipe->rawCommand(
                        'EVAL',
                        $luaScript,  // Lua脚本内容
                        1,           // KEYS的数量
                        $dailyKey,   // KEYS[1]
                        $duToDeduct  // ARGV[1]
                    );
                }
            });
        } catch (\Exception $e) {
            Log::error("扣减额度管道执行失败", [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            // 错误处理
            return $totalDu / 1000; // 返回全部金额需补扣
        }

//        Log::info("每日扣除结果", $results);
        $actualDeducted = array_sum($results);

        // 扣除月度总额度（实际扣除多少，就扣多少）
        if ($actualDeducted > 0) {
            Redis::decrBy($monthKey, $actualDeducted);
        }

        // 检查是否完全扣除
        if ($actualDeducted < $totalDu) {
            // 部分扣除成功，返回需要补扣的金额（转换为元）
            return ($totalDu - $actualDeducted) / 1000;
        }

        return 0; // 完全扣除
    }

}
